package com.ltmonitor.thread;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.print.DocFlavor.STRING;

import com.ltmonitor.service.IQueryService;
import com.ltmonitor.web.util.SpringApplicationContextHolder;
import com.sun.tools.classfile.InnerClasses_attribute.Info;

/**
 * 检查GPS轨迹补传服务线程，用于校验不连续轨迹是否已经上传
 * @author Administrator
 *
 */
public class CheckGpsInsertServiceThread extends BasicServiceThread {

	public CheckGpsInsertServiceThread(String name, int sleepNum) {
		super(name, sleepNum);
	}
	
	@Resource
	private IQueryService queryService;
	
	private String queryId = "dataProcess.selectDiscontinuityData";//查询不连续轨迹
	
	private String gpsQueryId = "dataProcess.selectGpsDataBetween2Points";//查询gps定位语句
	
	private String delQueryId = "dataProcess.delOneDisconData";//假删除不连续轨迹数据
	
	
	
	////////////////////////////////////屏蔽不参与补数据车辆所需
	private Map outMap = new HashMap <String,String>();
	
	private boolean outMapFlg = true;//定义outMap可更新标记为true，表示可更新
	
	private String outQueryId = "dataProcess.selectOutMapDatas";
	
	////////////////////////////////////校验车辆所需数据
	
	private boolean dataFlg = true;//获取数据标记，数据获取成功才可以进行数据校验
	private int dataFlgNum = 0;//获取数据标记统计数量，用于设定一轮校验完成后，经过几次循环方可进行下次校验
	private int dataFlgTotal = 40;//数据标记统计数量大于等于最大值，方可进行数据获取和校验
	
	private List disGpsDatas = new ArrayList ();//不连续轨迹数据保存列表，默认为空列表
	
	private  int checkIndex = 0;//需要校验的数据索引，默认为0
	
	
	
	/////////////////////////////////////////////////////////////////////////////////////////
	
	//初始化服务
		protected String threadServiceInit() {
			String msg = "";
			msg += initService();
			return msg;
		}
		
		//服务运行
		protected void threadServiceRun() {
			try {
				if(queryService != null) {
					
					if(dataFlg == true) {
						//允许获取数据
						getVehAndDisDatas();
					}else {
						//不允许获取数据，开始校验
						if(checkIndex < disGpsDatas.size()) {
//							outInfo("开始校验数据，当前数据索引：" + checkIndex);
							checkDiscontinuityData();//开始校验数据
							//校验数据
							checkIndex ++;//准备校验下一条
						}else {
							//超出索引
							dataFlgNum ++;
//							outInfo(" 校验索引超出范围，当前索引为：" + checkIndex + " ， 当前数据数量：" + disGpsDatas.size() +   " ，数据获取标记校验数量为：" + dataFlgNum);
							if(dataFlgNum >= dataFlgTotal) {
								//条件允许，可以进行下次校验
								outInfo("数据获取标记校验数量达到标准，当前数量为：" + dataFlgNum + " ， 允许重新获取数据并初始化");
								if(dataFlg == false) {
									dataFlg = true;
									dataFlgNum = 0;//重置数据标记校验数量									
								}
							}
						}
					}
									
				}else {
					outInfo("数据库查询服务对象为null！");
					checkError();
				}
			} catch (Exception e) {
				// TODO: handle exception
				outError("线程执行失败：" + e.getMessage());
			}
			
		}
		
	///////////////////////////////////////////获取需要屏蔽车辆数据和不连续轨迹数据
	//获取数据,条件:数据获取标记为true，同时，满足disGpsDatas列表为空，或者校验索引已经超出列表长度
	private void getVehAndDisDatas() {
		try {
			if (disGpsDatas.size() <= 0 || checkIndex >= disGpsDatas.size()) {
				getOutMapDatas();//获取无需补数据车辆信息
				getDisGpsData();//获取不连续轨迹数据;
				
				checkIndex = 0;//初始化校验数据为0
				dataFlg = false;//设置数据标记，	
			}	
		} catch (Exception e) {
			// TODO: handle exception
			outError("获取校验所需基本数据失败：" + e.getMessage());
		}
	}

	// 获取车辆信息并更新到Map中
	private void getOutMapDatas() {
		String msg = "";
		try {
//			outInfo("开始更新无需补数据车辆信息...................");
			List<Map<String, Object>> list = queryService.query(outQueryId, null);
			if (list != null && list.size() > 0) {
				outMap.clear();
				for (Map temp : list) {
					outMap.put(temp.get("simNo").toString(), "1");
				}
				msg += "更新无需补数据车辆数据成功，车辆数为：" + list.size();
				outInfo(msg);
			}
		} catch (Exception e) {
			// TODO: handle exception
			msg += "获取无需补数据车辆信息失败：" + e.getMessage();
			outError(msg);
		}

	}

	//获取不连续轨迹数据
	private void getDisGpsData() {
		try {
//			outInfo("开始获取不连续轨迹数据...................");
			Date time = new Date( new Date().getTime() - 1000 * 60 * 60 * 18);
			Map map = new HashMap ();
			map.put("startDate",time);
			disGpsDatas =  queryService.query(queryId, map);
			if(disGpsDatas == null) {
				//如果列表为null，则新建一个空列表
				disGpsDatas = new ArrayList();
			}
			outInfo("不连续轨迹数据获取完成，当前不连续轨迹数据数量为：" + disGpsDatas.size());
		} catch (Exception e) {
			// TODO: handle exception
			outError("获取本次不连续轨迹数据失败：" + e.getMessage());
		}
		
	}
	
	//////////////////////////////////////////////////////////校验不连续轨迹和无效点
	
	//校验不连续轨迹数据 
	private  void checkDiscontinuityData() {
		String msg = "";
		try {
			Map temp = (Map) disGpsDatas.get(checkIndex);
			if(temp != null) {
//				outInfo("索引号：" + checkIndex + " ， 校验数据：" + temp.toString());
				if(!isInOutMap(temp)) {
					if(checkValidGpsData(temp)) {//校验当前轨迹中是否存在有效数据
						delOneDisconData(temp);
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			msg += "校验不连续轨迹数据失败 ：" + e.getMessage();
			outError(msg);
			checkError();
		}
	}
	
	
	//校验不连续轨迹两点之间的有效数据，如果有数据，且数量合法，则返回true，如果没有数据，或者数量不合法，则返回false
	private boolean checkValidGpsData(Map map) {
		boolean flg = false;
		String msg  = "";
		try {
			long start = Calendar.getInstance().getTimeInMillis();
			//加入valid条件
			map.remove("valid");
			map.put("valid", 1);
			
			List list = queryService.query(gpsQueryId, map);
			if(list != null) {
				if(list.size() > 0) {
					Map temp = (Map) list.get(0);
					int nums = Integer.valueOf(temp.get("nums").toString());
					if(nums > 0) {
						flg = true;
						outInfo("索引号：" + checkIndex + " ，不连续轨迹数据为：" + map.toString());
						outInfo("当前不连续轨迹两点之间的有效gps数据数量为：" + nums + "  ， 需要删除当前不连续轨迹数据，重新获取！");
					}else {
//						outInfo("当前不连续轨迹两点之间的有效gps数据数量为0 ，无需重新获取！");
					}
				}
			}else {
				msg = "查询两点之间gps数据出错，数据对象为null！";
				outError(msg);
				checkError();
			}
			long end = Calendar.getInstance().getTimeInMillis();
			//如果校验时间大于2000 毫秒，则显示
			if(end - start >= 2000) {
				outInfo("索引号：" + checkIndex + " ， 本次校验时间为：" + (end-start) + "毫秒，轨迹数据为：" + map.toString());
			}
			
		} catch (Exception e) {
			// TODO: handle exception
			msg = "校验不连续轨迹点之间gps数据失败：" + e.getMessage();
			outError(msg);
			checkError();
		}

		return flg;
	}
	
	
	//开始进行假删除工作
	private void delOneDisconData(Map map) {
		String msg = "";
		String string = map.get("plateNo").toString() + " , ";
		try {
			queryService.update(delQueryId, map);
			msg += "假删除成功！";
		} catch (Exception e) {
			// TODO: handle exception
			msg += "假删除不连续轨迹数据失败：" + e.getMessage();
		}
		
		if(!msg.equals(""))
		{
			msg = string + msg;
			outInfo(msg);
		}
	}
	
	///////////////////////////////////////////获取需要屏蔽车辆数据和不连续轨迹数据
	
	
	
	
	//校验该数据所属车辆simNo是否在outMap中，如果在，则假删除该条数据
	private boolean isInOutMap(Map map) {
		boolean flg = false;
		String msg = "";
		try {
			if(map.containsKey("simNo")) {
				if(outMap.containsKey(map.get("simNo").toString())) {
					//开始删除单个数据
					outInfo("当前车辆需要屏蔽，开始假删除该不连续轨迹数据..............");
					outInfo("车辆数据为：" + map.toString());
					delOneDisconData(map);
					flg = true;
				}
			}else {
				msg += "当前车辆获取simNo号码失败，无法进行屏蔽判断,当前车辆数据：";
				outError(msg + map.toString());
			}
		} catch (Exception e) {
			// TODO: handle exception
			msg += "判断是否为需屏蔽车辆失败：" + e.getMessage();
			outError(msg);
			outError("车辆数据为：" + map.toString());
		}
		
		return flg;
	}
	
	
	////////////////////////////////////////////初始化数据服务
	
	//初始化所需服务
	private String  initService() {
		String msg = "";
		if(queryService == null) {
			queryService = SpringApplicationContextHolder.getBean("queryService");
			if(queryService == null) {
				msg += "查询服务对象创建失败！";
			}
		}
		return msg;
	}
}
